package org.longs;

import com.alibaba.fastjson2.JSON;
import org.longs.bean.Frame;
import org.longs.bean.*;
import org.longs.converter.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class Actuator {

    /**
     * 解析wdf并转换成png
     *
     * @param path 要解析的wdf文件
     * @param out  输出目录
     * @throws IOException 文件异常
     */
    public static void WdfConverterPng(String path, String out) throws IOException {
        WdfConverter wdfConverter = new WdfConverter(path);
        wdfConverter.analysis();
        for (WasConverter wasConverter : wdfConverter.getWasConverters()) {
            wasConverter.analysis();
            for (ImageFile imageFile : wasConverter.getImageFiles()) {
                BufferedImage bufferedImage = wasConverter.converterBufferedImage(imageFile);
//                File dir = new File(out + wasConverter.getName());
//                if (!dir.exists() && !dir.mkdir()) {
//                    throw new RuntimeException("创建文件夹失败");
//                }
                ImageIO.write(bufferedImage, "png", new File(out + File.separator + wasConverter.getName() + ".png"));
            }
        }
        wdfConverter.close();
    }

    public static void wasConverterPng(String path, String out) throws IOException {
        WasConverter wasConverter = new WasConverter(path);
        wasConverter.analysis();
//        BufferedImage bufferedImage = wasConverter.converterBufferedImage(wasConverter.getImageFiles().get(69));
        for (ImageFile imageFile : wasConverter.getImageFiles()) {
            BufferedImage bufferedImage = wasConverter.converterBufferedImage(imageFile);
            final BufferedImage image = new BufferedImage(wasConverter.getHeader().getWidth(), wasConverter.getHeader().getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
            Graphics2D graphics = image.createGraphics();
            Frame frame = imageFile.getFrame();
            graphics.drawImage(bufferedImage,
                    (wasConverter.getHeader().getWidth() - frame.getWidth()) / 2,
                    (wasConverter.getHeader().getHeight() - frame.getHeight()) / 2,
                    frame.getWidth(),
                    frame.getHeight(),
                    null);
            ImageIO.write(image, "png", new File(out + imageFile.getHash() + ".png"));
        }
    }

    public static void wasConverterSpirit(String path, String out) throws IOException {
        if (path.endsWith("json")) {
            return;
        }
        WasConverter wasConverter = new WasConverter(path);
        wasConverter.analysis();
        wasConverter.setName("spirit");
        for (ImageFile imageFile : wasConverter.getImageFiles()) {
            wasConverter.converterBufferedImage(imageFile);
        }
        converterSpirit(out, wasConverter);
    }

    public static void wasConverterSpirit(String path, String out, String name) throws IOException {
        wasConverterSpirit(path, out, name, true);

    }

    public static void wasConverterSpirit(String path, String out, String name, boolean flag) throws IOException {
        if (path.endsWith("json")) {
            return;
        }
        if (path.endsWith("png")) {
            return;
        }
        WasConverter wasConverter = new WasConverter(path);
        wasConverter.analysis();
        wasConverter.setName(name.replace(".was", ""));
        for (ImageFile imageFile : wasConverter.getImageFiles()) {
            wasConverter.converterBufferedImage(imageFile);
        }
        converterSpirit(out + "/", wasConverter);
        if (flag) {
            WasHeader header = wasConverter.getHeader();
            try (FileWriter fileWriter = new FileWriter(out + File.separator + name.replace(".was", "") + ".json")) {
                fileWriter.write(JSON.toJSONString(header));
            }
        }
        System.out.println("name::" + wasConverter.getName());
    }


    public static void wasConverterPng(String path, String out, int i) throws IOException {
        WasConverter wasConverter = new WasConverter(path);
        wasConverter.analysis();
        for (ImageFile imageFile : wasConverter.getImageFiles()) {
            BufferedImage bufferedImage = wasConverter.converterBufferedImage(imageFile);
            ImageIO.write(bufferedImage, "png", new File(out + imageFile.getHash() + i + ".png"));
        }
    }

    public static void WdfConverterSpiritToName(String path, String out, String key) throws IOException {
        WdfConverterSpiritToName(path, out, key, key);
    }

    public static void WdfConverterSpiritToName(String path, String out, String key, String name) throws IOException {
        WdfConverter wdfConverter = new WdfConverter(path);
        wdfConverter.analysis();
        WasConverter wasConverter = wdfConverter.getWasConverterMap().get(key.replace("0x", "").replace("0X", "").toLowerCase());
        wasConverter.analysis();
        for (ImageFile imageFile : wasConverter.getImageFiles()) {
            wasConverter.converterBufferedImage(imageFile);
        }
        converterSpirit(out, wasConverter, name);

        wdfConverter.close();
    }

    /**
     * 解析wdf并转换成精灵大图
     *
     * @param path 要解析的wdf文件
     * @param out  输出目录
     * @throws IOException 文件异常
     */
    public static void WdfConverterSpirit(String path, String out) throws IOException {
        WdfConverter wdfConverter = new WdfConverter(path);
        wdfConverter.analysis();
        for (int i = wdfConverter.getWasConverters().size() - 1; i >= 0; i--) {
            WasConverter wasConverter = wdfConverter.getWasConverters().get(i);
            System.out.println("name::" + wasConverter.getName());
            wasConverter.analysis();
            List<ImageFile> imageFiles = wasConverter.getImageFiles();
            if (imageFiles == null) {
                continue;
            }
            for (ImageFile imageFile : wasConverter.getImageFiles()) {
                wasConverter.converterBufferedImage(imageFile);
            }
            converterSpirit(out, wasConverter);
            wdfConverter.getWasConverters().remove(wasConverter);
        }
        wdfConverter.close();
    }


    /**
     * 解析wdf并转换wav音频
     *
     * @param path 要解析的wdf文件
     * @param out  输出目录
     * @throws IOException 文件异常
     */
    public static void WdfConverterWav(String path, String out) throws IOException {
        WdfWavConverter wdfConverter = new WdfWavConverter(path);
        wdfConverter.analysis();
        for (int i = wdfConverter.getWavConverters().size() - 1; i >= 0; i--) {
            WavConverter wasConverter = wdfConverter.getWavConverters().get(i);
            System.out.println("name::" + wasConverter.getName());
            wasConverter.analysis();
            try (FileOutputStream fos = new FileOutputStream(out + File.separator + wasConverter.getName() + ".wav")) {
                fos.write(wasConverter.getBytes()); // 将字节数组写入文件
            } catch (IOException e) {
                e.printStackTrace();
            }
            wdfConverter.getWavConverters().remove(wasConverter);
        }
        wdfConverter.close();
    }


    public static void converterAvatar(String out, String name, WasConverter wasConverter) throws IOException {
        File file = new File(out);
        if (!file.exists()) {
            file.mkdirs();
        }
        ImageFile imageFile = wasConverter.getImageFiles().get(0);
        ImageIO.write(imageFile.getBufferedImage(), "png", new File(out + "/" + name + ".png"));
    }

    public static void converterSpirit(String out, String name, WasConverter wasConverter) throws IOException {
        File file = new File(out);
        if (!file.exists()) {
            file.mkdirs();
        }
        WasHeader header = wasConverter.getHeader();
        if (header.getGroup() == 1 && header.getFrame() == 1) {
            ImageFile imageFile = wasConverter.getImageFiles().get(0);
            ImageIO.write(imageFile.getBufferedImage(), "png", new File(out + "/" + name + ".png"));
            imageFile.setBufferedImage(null);
            wasConverter.setImageFiles(null);
            return;
        }
        int index = 0;
        BufferedImage image = new BufferedImage(header.getWidth() * header.getFrame(), header.getHeight() * header.getGroup(), BufferedImage.TYPE_4BYTE_ABGR);
        for (int y = 0; y < header.getGroup(); y++) {
            for (int x = 0; x < header.getFrame(); x++) {
                if (index >= wasConverter.getImageFiles().size()) {
                    break;
                }
                ImageFile imageFile = wasConverter.getImageFiles().get(index++);
                Graphics2D graphics = image.createGraphics();
                Frame frame = imageFile.getFrame();
                int startX = x * header.getWidth() + header.getKeyX() - frame.getKeyX();
                if (startX < 0) {
                    startX = 0;
                }
                int startY = y * header.getHeight() + header.getKeyY() - frame.getKeyY();
                if (startY < 0) {
                    startY = 0;
                }
                graphics.drawImage(imageFile.getBufferedImage(),
                        startX,
                        startY,
                        frame.getWidth(),
                        frame.getHeight(),
                        null);

                imageFile.setBufferedImage(null);
            }
        }
        wasConverter.setImageFiles(null);
        ImageIO.write(image, "png", new File(out + "/" + name + ".png"));
    }


    public static void converterSpirit(String out, WasConverter wasConverter, String name) throws IOException {
        File file = new File(out);
        if (!file.exists()) {
            file.mkdirs();
        }
        WasHeader header = wasConverter.getHeader();
        if (header.getGroup() == 1 && header.getFrame() == 1) {
            ImageFile imageFile = wasConverter.getImageFiles().get(0);
            ImageIO.write(imageFile.getBufferedImage(), "png", new File(out + name + ".png"));
            imageFile.setBufferedImage(null);
            wasConverter.setImageFiles(null);
            return;
        }
        int index = 0;
        BufferedImage image = new BufferedImage(header.getWidth() * header.getFrame(), header.getHeight() * header.getGroup(), BufferedImage.TYPE_4BYTE_ABGR);
        for (int y = 0; y < header.getGroup(); y++) {
            for (int x = 0; x < header.getFrame(); x++) {
                if (index >= wasConverter.getImageFiles().size()) {
                    break;
                }
                ImageFile imageFile = wasConverter.getImageFiles().get(index++);
                Graphics2D graphics = image.createGraphics();
                Frame frame = imageFile.getFrame();
                int startX = x * header.getWidth() + header.getKeyX() - frame.getKeyX();
                if (startX < 0) {
                    startX = 0;
                }
                int startY = y * header.getHeight() + header.getKeyY() - frame.getKeyY();
                if (startY < 0) {
                    startY = 0;
                }
                graphics.drawImage(imageFile.getBufferedImage(),
                        startX,
                        startY,
                        frame.getWidth(),
                        frame.getHeight(),
                        null);

                imageFile.setBufferedImage(null);
            }
        }
        wasConverter.setImageFiles(null);
        ImageIO.write(image, "png", new File(out + "/" + name + ".png"));
        try (FileWriter fileWriter = new FileWriter(out + "/" + name + ".json")) {
            fileWriter.write(JSON.toJSONString(header));
        }
    }

    public static void converterSpirit(String out, WasConverter wasConverter) throws IOException {
        converterSpirit(out, wasConverter, wasConverter.getName());
    }


    public static void mapConverterPng(String path, String out) throws IOException {
        File file = new File(path);
        if (!file.exists()) {
            return;
        }
        if (!file.isDirectory()) {
            return;
        }
        try (Stream<Path> files = Files.list(Paths.get(file.getAbsolutePath()))) {
            files.forEach(item -> {
                try {
                    extracted(out, item.toFile());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public static void extractedMap(String out, File file) throws IOException {
        String fileName = file.getName().split("\\.")[0];
        fileName = fileName.replace("381990860", "");
        System.out.println(fileName);
        File dir = new File(out + "scene");
        if (!dir.exists() && !dir.mkdirs()) {
            return;
        }
        MapConverter converter = getMapConverter(file.getAbsolutePath());
        if (converter == null) {
            return;
        }
        BufferedImage image = new BufferedImage(converter.getMapHeader().getMapColNum() * 320, converter.getMapHeader().getMapRowNum() * 240, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = image.createGraphics();
        int count = 0;
        for (int y = 0; y < converter.getMapHeader().getMapRowNum(); y++) {
            for (int x = 0; x < converter.getMapHeader().getMapColNum(); x++) {
                MapBlock mapBlock = converter.getMapBlockList().get(count++);
                MapBean bean = new MapBean();
                bean.setX(x);
                bean.setY(y);
                int startX = x * mapBlock.getWidth();
                if (startX < 0) {
                    startX = 0;
                }
                int startY = y * mapBlock.getHeight();
                if (startY < 0) {
                    startY = 0;
                }
                graphics.drawImage(mapBlock.getBufferedImage(), startX, startY, mapBlock.getWidth(), mapBlock.getHeight(), null);
                mapBlock.setBufferedImage(null);
            }
        }
        ImageIO.write(image, "png", new File(dir.getAbsolutePath() + File.separator + fileName + ".png"));

    }

    public static void extracted(String out, File file) throws IOException {
        String fileName = file.getName().split("\\.")[0];
        fileName = fileName.replace("381990860", "");
        System.out.println(fileName);
        File dir = new File(out + "scene" + File.separator + fileName);
        if (!dir.exists() && !dir.mkdirs()) {
            return;
        }
        MapConverter converter = getMapConverter(file.getAbsolutePath());
        for (MapBlock block : converter.getMapBlockList()) {
            ImageIO.write(block.getBufferedImage(), "png", new File(dir.getAbsolutePath() + File.separator + block.getCol() + "-" + block.getRow() + ".png"));
            block.setBufferedImage(null);
        }
        dir = new File(out + File.separator + "mask" + File.separator + fileName);
        if (!dir.exists() && !dir.mkdirs()) {
            return;
        }
        BufferedImage image = new BufferedImage(converter.getMapHeader().getMapColNum() * 320, converter.getMapHeader().getMapRowNum() * 240, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D graphics = image.createGraphics();
        for (Mask mask : converter.getMaskList()) {
            converter.converterMask(mask);
            converter.setMaskBufferedImage(mask);
            graphics.drawImage(mask.getBufferedImage(), mask.getKeyX(), mask.getKeyY(), mask.getWidth(), mask.getHeight(), null);
            mask.setBufferedImage(null);
        }
        List<MapBean> mapBeans = subImage(converter, image);
        for (MapBean bean : mapBeans) {
            ImageIO.write(bean.getImage(), "png", new File(dir.getAbsolutePath() + File.separator + bean.getX() + "-" + bean.getY() + ".png"));
            bean.setImage(null);
        }
        dir = new File(out + File.separator + "info");
        if (!dir.exists() && !dir.mkdirs()) {
            return;
        }
        MapHeader mapHeader = converter.getMapHeader();
        try (FileWriter fileWriter = new FileWriter(dir.getAbsolutePath() + File.separator + fileName + ".json")) {
            fileWriter.write(JSON.toJSONString(mapHeader));
        }
        dir = new File(out + File.separator + "terrain");
        if (!dir.exists() && !dir.mkdirs()) {
            return;
        }
        ArrayList<TerrainBean> terrain = converter.converterTerrain();
        try (FileWriter fileWriter = new FileWriter(dir.getAbsolutePath() + File.separator + fileName + ".json")) {
            fileWriter.write(JSON.toJSONString(terrain));
        }
    }

    private static MapConverter getMapConverter(String path) throws IOException {
        MapConverter converter = new MapConverter(path);
        converter.analysis();
        int count = 0;
        if (converter.getMapBlockList() == null) {
            return null;
        }
        for (MapBlock mapBlock : converter.getMapBlockList()) {
            mapBlock.setIndex(count++);
            converter.converterBlock(mapBlock);
        }
        return converter;
    }


    private static List<MapBean> subImage(MapConverter mapHeader, BufferedImage image) {
        ArrayList<MapBean> list = new ArrayList<>();
        int count = 0;
        for (int y = 0; y < mapHeader.getMapHeader().getMapRowNum(); y++) {
            for (int x = 0; x < mapHeader.getMapHeader().getMapColNum(); x++) {
                MapBlock mapBlock = mapHeader.getMapBlockList().get(count++);
                MapBean bean = new MapBean();
                bean.setX(x);
                bean.setY(y);
                int startX = x * mapBlock.getWidth();
                if (startX < 0) {
                    startX = 0;
                }
                int startY = y * mapBlock.getHeight();
                if (startY < 0) {
                    startY = 0;
                }
                bean.setImage(image.getSubimage(startX, startY, mapBlock.getWidth(), mapBlock.getHeight()));
                list.add(bean);
            }
        }
        return list;
    }
}